#include"../include/parsing_lr0.h"

#define MAX_LINE_LEN 1024  // 根据实际需求调整缓冲区大小
typedef struct GLR_CSS{
	int num;//条的编号 
	char left;//产生式左边
	char right[30];//产生式右边 
	int dot;//用于存储点的位置 
	struct GLR_CSS *next; 
}CSS; 

typedef struct GLR{
	int I_01;//存放自己是I几
	int I_02;//存放是经过I几通过输入c变换过来的 
	char c; //I01输入c到I02
	
	struct GLR_CSS *css;//头指针 
	
	int num;//产生式的个数
	
	struct GLR *next; 
		 
}LR;

char *g[100];
int n;//文法的条数 
char at[100];//存储终结符
int at_num=0; //用于记录at数组的长度 
char gt[100];//存储非终结符 
char gt_01[100][2];//第一个存储非终结符，第二个存储记录 
int gt_num=0;//用于记录gt数组的长度 
LR lr;//用于存储输入的文法 
LR *I; 
LR *Ips;//存储头结点 
LR *Ipf;//存储最后一个结点
int act_gt[100][100]; 
char *str;//需要分析的输入串 
int str_num;//分析串栈的指针 
int fhz[100];//符号栈 
int fhz_num;//符号栈的指针 
int idx=0;

// 去除字符串首尾空格（包括换行符和制表符）
char* trim_whitespace(char* str) {
    if (str == NULL) return NULL;

    // 去除头部空格
    char* start = str;
    while (isspace((unsigned char)*start)) {
        start++;
    }

    // 处理全空行的情况
    if (*start == '\0') {
        str[0] = '\0';
        return str;
    }

    // 去除尾部空格
    char* end = str + strlen(str) - 1;
    while (end > start && isspace((unsigned char)*end)) {
        end--;
    }
    *(end + 1) = '\0';  // 截断尾部空格

    // 将处理后的字符串前移
    if (start != str) {
        memmove(str, start, end - start + 2);  // +2 包含结束符
    }

    return str;
}

//接收输入的文法 
void get_g(char*rulefile){
	int i=0;
	FILE* file = fopen(rulefile, "r");
    if (!file) {
        perror("无法打开文件");
        return;
    }

    char buffer[MAX_LINE_LEN];
    while (fgets(buffer, sizeof(buffer), file)) {
        // 去除换行符（可选）
        buffer[strcspn(buffer, "\n")] = '\0';

        // 去除首尾空格
        trim_whitespace(buffer);

        g[i++]=strdup(buffer);
    }
    n=i;
    fclose(file);
} 

//查重action表 
void action_01(char c){
	
	if(at_num==0){//没有直接放 
		at[at_num]=c; 
		at_num++;
	}else{//有，查重 
		int i;
		int flag=0;
		for(i=0;i<at_num;i++){
			if(at[i]==c){
				flag=1;
			}
		} 
		
		if(flag==0){//没有 
			at[at_num]=c;
			at_num++; 
		}
	}
	
}

//找出action表 
void action(){//找action序列（非大写）
	int i; //遍历每一条 
	int j;//遍历每一条的每一个 
	int len;
	for(i=0;i<n;i++){
		len=strlen(g[i]);
		for(j=0;j<len;j++){
			if(g[i][j]=='-'&&g[i][j+1]=='>'){//排除->(排除箭头，也就是“定义为”) 
				
				j++;
				continue;
			}else{
				
				if(g[i][j]<65||g[i][j]>90){//终结符的范围 
					action_01(g[i][j]); //放入at数组，//该函数用于检测是否重复
				}
				
				 
			}
		}
	}
	
	at[at_num]='#';
	at_num++;
	at[at_num]='\0';
	 
	
} 

//查重goto表 
void gotoo_01(char c){
	
	if(gt_num==0){//没有直接放 
		gt[gt_num]=c; 
		gt_num++;
	}else{//有，查重 
		int i;
		int flag=0;
		for(i=0;i<gt_num;i++){
			if(gt[i]==c){
				flag=1;
			}
		} 
		
		if(flag==0){//没有 
			gt[gt_num]=c;
			gt_num++; 
		}
	}
	
}

//找出goto表 
void gotoo(){//找goto序列（大写）
	int i; //遍历每一条 
	int j;//遍历每一条的每一个 
	int len;
	for(i=0;i<n;i++){
		len=strlen(g[i]);
		for(j=0;j<len;j++){
			if(g[i][j]=='-'&&g[i][j+1]=='>'){//排除->(排除箭头，也就是“定义为”) 
				j++;
				continue;
			}else{
				
				if(g[i][j]>=65&&g[i][j]<=90){//非终结符的范围
					gotoo_01(g[i][j]); //放入gt数组，//该函数用于检测是否重复 
				} 
				
				
			}
		}
	}
	
	
	gt[gt_num]='\0';
}

void init_gt_01(){
	int i;
	for(i=0;i<gt_num;i++){
		gt_01[i][0]=gt[i];
		gt_01[i][1]=0;//未检测时为0； 
	}
}

//测试，输出结构体
void f(CSS *p){
	
	int i=1;
	while(p!=NULL){
		printf("(%d)%c->%s\n",i,p->left,p->right);
		printf("点：%d\n",p->dot);
		p=p->next;
		i++;
	}
	
} 

//将所有文法存储在lr变量中 
void lr_save(){
	lr.num=n;//存储初始文法的条数
	int i,j;
	int len;
	CSS *cssp,*cssk,*csst;
	
	cssp=(CSS*)malloc(sizeof(CSS));//头结点 
	cssk=cssp; 
	for(i=0;i<n;i++){
		len=strlen(g[i]);
		
		csst=(CSS*)malloc(sizeof(CSS));
		csst->num=i+1; //存储是第几条文法 
		csst->left=g[i][0];//存储左边
		int k=0;
		
		for(j=3;j<len;j++){
			
			csst->right[k]=g[i][j];
			k++; 
			 
		}
		csst->right[k]='\0';
		cssk->next=csst;
		cssk=cssk->next;
		
	} 
	
	cssk->next=NULL;
	lr.css=cssp;
	
	
	//fff();//测试，输出函数 
	
	 
}

//初始化I0;并初始头结点
void into_I0(){
	//空结点 
	Ips=(LR*)malloc(sizeof(LR));
	
	//临时结点
	LR *Ipt;
	Ipt=(LR*)malloc(sizeof(LR));
	//Ipt->num=1;//文法条数 
	
	//初始化第一个数据结点 
	Ipt->I_01=0;//I0
	
	//定义语句的临时结点 ,和转移结点 
	CSS *csst,*csss;
	
	//定义遍历的结点 
	CSS *cssk;
	cssk=lr.css->next;
	
	//语句的第一个空结点 
	Ipt->css=(CSS*)malloc(sizeof(CSS));
	csss=Ipt->css;
	//语句初始个数
	Ipt->num=0; 
	int bt=-1;
	
	//E'->E
	bt++;//表达式的序号 
	csst =(CSS*)malloc(sizeof(CSS)); 
	//表达式的序号
	csst->num=bt; 
		
	//点的位置 
	csst->dot=0;
	//表达式左边
	csst->left='S';
	//表达式右边
	csst->right[0]=cssk->left; 
	csst->right[1]='\0';
		
	csss->next=csst;
	csss=csss->next;
		//cssk=cssk->next;	
	Ipt->num++;//语句条数加1 
	
	while(cssk!=NULL){
		bt++;//表达式的序号 
		csst =(CSS*)malloc(sizeof(CSS)); 
		//表达式的序号
		csst->num=bt; 
		
		//点的位置 
		csst->dot=0;
		//表达式左边 复制 
		csst->left=cssk->left;
		//表达式右边复制 
		strcpy(csst->right,cssk->right); 
		
		csss->next=csst;
		csss=csss->next;
		cssk=cssk->next;
		
		Ipt->num++;//语句条数加1 
			
	}
		
	csss->next=NULL; 
	
	Ips->next=Ipt;//头 
	Ipf=Ips->next;//指向尾巴 
	Ipf->next=NULL;
	
	//fff();	 
} 

int jc_gt_01(char c){//c处为0返回1，否则返回0 
	int i;
	for(i=0;i<gt_num;i++){
		if(gt_01[i][0]==c){
			if(gt_01[i][1]==0){
				return 1;
			}else{
				return 0;
			} 
			
		}
	} 
	
	return 0;
}

void fz_gt_01(int c){
	
	int i;
	for(i=0;i<gt_num;i++){
		if(gt_01[i][0]==c){
			gt_01[i][1]=1;			
		}
	} 
	
} 

void create_I(LR *lrr,CSS *css){
	
	//清空gt_01数组 
	init_gt_01();
	
	char s=css->right[css->dot];//当前移入的符号 
	
	//(1)遍历lrr结点所有表达式，生成新的I结点
	//开辟I结点存储空间 
	LR *ln=(LR*)malloc(sizeof(LR));
	ln->num=0;//文法初始条数 
	
	// 生成新表达式的csss
	CSS *csss,*csst;
	csss=(CSS*)malloc(sizeof(CSS));//头结点
	ln->css=csss;//链上带头结点
	csss->next=NULL; 
	
	//遍历每条表达式的临时变量 
	CSS *lt=lrr->css->next;
	while(lt!=NULL){
		if(lt->right[lt->dot]==s){//点后面是要移入的符号 
			csst=(CSS*)malloc(sizeof(CSS));//开辟一个表达式的存储空间 
			csst->next=NULL;//next复制NULL
			csst->left=lt->left;
			strcpy(csst->right,lt->right);
			csst->dot=lt->dot+1;
			
			
			csss->next=csst;
			csss=csss->next;
			
			ln->num++; 
			
		}
		
		lt=lt->next;
	} 
	
	
	
	
	//（2）判断新结点的每个表达式后是否是终结符，若不是则新添加 
	
	//csss目前指向最后一个
	CSS *csss01=ln->css->next;
	CSS *csss02; 
	
	//char pre='a'; 
	
	while(csss01!=NULL){//循环目前生成的表达式 
		if(csss01->right[csss01->dot]>=65&&csss01->right[csss01->dot]<=90&&jc_gt_01(csss01->right[csss01->dot])==1){//非终结符判断条件
			
			//printf("ssssssssssss\n");
			
			csss02=Ips->next->css->next;//I0的所有表达式 
			while(csss02!=NULL){
				if(csss02->left==csss01->right[csss01->dot]){
					csst=(CSS*)malloc(sizeof(CSS));//开辟一个表达式的存储空间 
					csst->next=NULL;//next复制NULL
					csst->left=csss02->left;
					strcpy(csst->right,csss02->right);
					csst->dot=csss02->dot;
					
					csss->next=csst;
					csss=csss->next;
					
					ln->num++;
				}
				csss02=csss02->next;
			}
			
			fz_gt_01(csss01->right[csss01->dot]);
		}
		
		csss01=csss01->next; 
	} 
	
	
	
	
		
	
	//(3)查重
	LR *Ipt01=Ips->next;
	CSS *csss03;
	CSS *csss04;
	
	int flag=0;
	
	while(Ipt01!=NULL){
		
		
		if(Ipt01->num==ln->num){//语法条数相等才有相同的可能性
		
		
			csss03=Ipt01->css->next;
			flag=0;
			while(csss03!=NULL){
				csss04=ln->css->next;
				while(csss04!=NULL){
					
					if(csss04->left==csss03->left&&csss04->dot==csss03->dot&&strcmp(csss03->right,csss04->right)==0){
						flag++;
					} 
					
					csss04=csss04->next;
				} 
				
				csss03=csss03->next;
			}
			
			if(flag==ln->num){//重复了 
				return;
			} 
			 
			
		}
		
		
		
		
		Ipt01=Ipt01->next;
	}
	
	
	
	 
	
	
	//加到末尾
	
	ln->I_01=Ipf->I_01+1;
	ln->I_02=lrr->I_01;
	ln->c=s;
	
	
	Ipf->next=ln;
	Ipf=Ipf->next;
	Ipf->next=NULL;
	
	/*printf("-------------------\n");
	printf("这是I(%d)\n",ln->I_01);
	printf("I(%d)输入%c变成\n",ln->I_02,ln->c);
	printf("表达式为:\n");
	f(ln->css->next);
	printf("-------------------\n"); */ 
	
}

//将所有项目I0---In列出 
void lr_analyse(){
	
	
	
	LR *Ipt_01;//用于遍历 
	LR *Ipt_02; //用于开辟新结点
	
	CSS *csst_01;//遍历
	CSS *csst_02; 
	
	Ipt_01=Ips->next;
	
	// lr_analyse_exit()==1
	while(1){//项目列表的最后一个所有语法的点都在最后面则退出 ,遍历I列表，每次一个 
		
		csst_01=Ipt_01->css->next;//In的第一个产生式子的位置 
		
		
		while(csst_01!=NULL){//当前I的第j个表达式点后移，产生新的 
		//移动点
		//
		//printf("222222222\n");
			if(csst_01->dot==strlen(csst_01->right)){//已经完了 
				csst_01=csst_01->next;
				continue; 
			}else{
				//printf("-------当前遍历的是I(%d)的%c->%s语句-------\n",Ipt_01->I_01,csst_01->left,csst_01->right);
				create_I(Ipt_01,csst_01);//传入当前I的所有表达式的头，和当前语句 
			}
			 
			
			csst_01=csst_01->next;
			
		} 
		
		//printf("11111111111122222222222222222222222222");
		
		if(Ipt_01->I_01==Ipf->I_01){
			break;
		}else{
			
			Ipt_01=Ipt_01->next;
			//printf("11111111111111111111111111\n");
		}
		
		
		
	}
	
}

void acc_form(){
	act_gt[1][strlen(at)-1]=999;
}

//检测是不是lt02移入lt01->c,变成lt01
void goto_form_01(LR *lt01,LR *lt02,char c){
	
	CSS *csst01;
	csst01=lt02->css->next;//lt02的第一条语句
	
	//移入后的新语句头 
	CSS *csst02; 
	csst02=(CSS*)malloc(sizeof(CSS));
	csst02->next=NULL;
	//移动临时变量
	CSS *csst03,*csst04;
	csst03=csst02;
	
	while(csst01!=NULL){
		
		if(csst01->right[csst01->dot]==c){
			
			//printf("77888888999\n");
			
			//申请空间 
			csst04=(CSS*)malloc(sizeof(CSS));
			//填写表达式左边数据 
			csst04->left=csst01->left;
			//右边数据 
			strcpy(csst04->right,csst01->right);
			//点 
			csst04->dot=csst01->dot+1;
			
			csst04->next=NULL;
			
			csst03->next=csst04;
			csst03=csst03->next; 
			
			
		}
		
		csst01=csst01->next;
	} 
	
	//查看csst02是否与lt01表达式相同
	int flag=0;
	csst02=csst02->next;
	/*printf("=======这是csst02=======\n");
	f(csst02);
	printf("=======这是csst02=======\n");*/
	
	CSS *csst05;
	while(csst02!=NULL){
		csst05=lt01->css->next;
		while(csst05!=NULL){
			//printf("777777777\n");
			if(csst05->left==csst02->left&&csst05->dot==csst02->dot&&strcmp(csst05->right,csst02->right)==0){
			
				flag++;
				
			}
			
			csst05=csst05->next;
		}
		
		csst02=csst02->next;
		
	} 
	
	//printf("flag==%d,lt01->num=%d\n",flag,lt01->num);
	
	if(flag==lt01->num){
		
		//说明lt02移入c，变成lt01
		
		//纵坐标
		int h=lt02->I_01;
		//横坐标
		int x;
		int i;
		for(i=0;i<gt_num;i++){
			if(gt[i]==c){
				x=i;
			}
		} 
		
		act_gt[h][at_num+x]=lt01->I_01;
		
	}
	
	//移入 
	
}

void goto_form(){
	//遍历除I0所有LR->c为大写的
	LR *lt01;
	lt01=Ips->next->next;//I1
	LR *lt02;//I0
	
	while(lt01!=NULL){
		
		if(lt01->c>=65&&lt01->c<=90){//lt01是由某个状态移入c变成的 
			lt02=Ips->next;//从I0，开始 
			while(lt02!=NULL){
				
				//检测是不是lt02移入lt01->c,变成lt01 
				goto_form_01(lt01,lt02,lt01->c);//并填写goto表 
				lt02=lt02->next;
				
			}
			
		}
		
		lt01=lt01->next;
	} 
}

void action_r_form_01(int h,CSS *csst){//(纵坐标,当前表达式)在I0中找到，并填表 
	CSS *csst01=Ips->next->css;
	while(csst01!=NULL){
		if(csst01->left==csst->left&&strcmp(csst01->right,csst->right)==0){
			
			int num=csst01->num*(-1);//编号 
			//填表
			int i;
			for(i=0;i<at_num;i++){
				act_gt[h][i]=num;
			}
			 
		}
		
		csst01=csst01->next;
	}
	
}

void action_r_form(){
	//遍历I1开始
	//如果In的某条文法的点在最后，则在I0的css中找对应的编号 ，（除left=S的情况，因为这个是acc） 

	LR *lt01=Ips->next->next;
	CSS *csst01;
	
	
	while(lt01!=NULL){
		
		csst01=lt01->css->next;
		while(csst01!=NULL){
			
			if(csst01->left!='S'&&csst01->dot==strlen(csst01->right)){
				action_r_form_01(lt01->I_01,csst01);//在I0中找到，并填表 
			}
			
			csst01=csst01->next;
		}
		
		lt01=lt01->next;
		
	} 
}

//检测是不是lt02移入lt01->c,变成lt01
void action_s_form_01(LR *lt01,LR *lt02,char c){
	
	init_gt_01();//清空gt_01数组 
	
	
	CSS *csst01;
	csst01=lt02->css->next;//lt02的第一条语句
	
	//移入后的新语句头 
	CSS *csst02; 
	csst02=(CSS*)malloc(sizeof(CSS));
	csst02->next=NULL;
	//移动临时变量
	CSS *csst03,*csst04;
	csst03=csst02;
	
	while(csst01!=NULL){
		
		if(csst01->right[csst01->dot]==c){
			
			//printf("77888888999\n");
			
			//申请空间 
			csst04=(CSS*)malloc(sizeof(CSS));
			//填写表达式左边数据 
			csst04->left=csst01->left;
			//右边数据 
			strcpy(csst04->right,csst01->right);
			//点 
			csst04->dot=csst01->dot+1;
			
			csst04->next=NULL;
			
			csst03->next=csst04;
			csst03=csst03->next;
			
			
			
			
			//printf("%c",csst04->right[csst04->dot]);	
		}
		//printf("qqqqqqqqqqqqqqqqqqqq\n");
			
		csst01=csst01->next;
	} 
	
	
	//将csst02中的非终结符在I0中找出,现在csst03所指最后一个表达式 
	CSS *csst02_01=csst02->next;
	while(csst02_01!=NULL){
		char cc=csst02_01->right[csst02_01->dot];
		if(cc>=65&&cc<=90&&jc_gt_01(cc)==1){
			//遍历I0
			CSS *cssi0=Ips->next->css->next;
			while(cssi0!=NULL){
				
					if(cssi0->left==cc){
						//申请空间 
						csst04=(CSS*)malloc(sizeof(CSS));
						//填写表达式左边数据 
						csst04->left=cssi0->left;
						//右边数据 
						strcpy(csst04->right,cssi0->right);
						//点 
						csst04->dot=cssi0->dot;
			
						csst04->next=NULL;
			
						csst03->next=csst04;
						csst03=csst03->next; 
					}
				
				
					cssi0=cssi0->next;
				}
			
			
			
				fz_gt_01(cc); 
			
		}
		
		csst02_01=csst02_01->next;
	} 
	 
	
	
	
	//查看csst02是否与lt01表达式相同
	int flag=0;
	csst02=csst02->next;
	/*printf("=======这是csst02=======\n");
	f(csst02);
	printf("=======这是csst02=======\n");*/
	
	
	/*if(lt01->I_01==3){
		printf("这是I3,,I%d正在与他比较\n",lt02->I_01);
		printf("生成的东西为：\n");
		f(csst02);
		printf("%c\n",lt01->c);
	}*/ 
	
	
	CSS *csst05;
	while(csst02!=NULL){
		csst05=lt01->css->next;
		while(csst05!=NULL){
			//printf("777777777\n");
			if(csst05->left==csst02->left&&csst05->dot==csst02->dot&&strcmp(csst05->right,csst02->right)==0){
			
				flag++;
				
			}
			
			csst05=csst05->next;
		}
		
		csst02=csst02->next;
		
	} 
	
	
	
	//printf("flag==%d,lt01->num=%d\n",flag,lt01->num);
	
	if(flag==lt01->num){
		
		//说明lt02移入c，变成lt01
		
		
		//纵坐标
		int h=lt02->I_01;
		//横坐标
		int x;
		
		int i;
		for(i=0;i<at_num;i++){
			if(at[i]==c){
				x=i;
			}
		} 
		
		act_gt[h][x]=lt01->I_01;
		
	}
	
	//移入 
}

void action_s_form(){
	//遍历除I0所有LR->c为非大写的，也就是终结符 
	LR *lt01;
	lt01=Ips->next->next;//I1
	LR *lt02;//I0
	
	while(lt01!=NULL){
		
		if(lt01->c<65||lt01->c>90){//lt01是由某个状态移入c变成的 
			lt02=Ips->next;//从I0，开始 
			while(lt02!=NULL){
				
				//检测是不是lt02移入lt01->c,变成lt01 
				action_s_form_01(lt01,lt02,lt01->c);//并填写goto表 
				lt02=lt02->next;
				
			}
			
		}
		
		lt01=lt01->next;
	} 
	
}

void output_action_goto(){
	int i;
	int j;
	int k;
	int q;
	int w;
	printf("--------ACTION-------------------GOTO-------\n"); 
	printf(" 状态");
	for(q=0;q<at_num;q++){
		printf("%5c",at[q]);
	} 
	for(k=0;k<gt_num;k++){//goto表的表头 
		printf("%5c",gt[k]);
	} 
	
	printf("\n");
	
	for(i=0;i<=Ipf->I_01;i++){
		printf("%5d",i);//状态
		
		//输出action表的值 
		for(w=0;w<at_num;w++){
			if(act_gt[i][w]==999){
				printf("  acc");
				continue;
			}
			
			if(act_gt[i][w]<0){
				printf("   R%d",act_gt[i][w]*-1);
				continue;
			}
			
			if(act_gt[i][w]>0){
				printf("   S%d",act_gt[i][w]);
				continue;
			}
			
			
			
			printf("%5c",' ');
			
			
		} 
		//输出goto表的值 
		for(j=0;j<gt_num;j++){
			if(act_gt[i][at_num+j]==0){
				printf("%5c",' ');
			}else{
				printf("%5d",act_gt[i][at_num+j]);
			} 
			
		}
		
		printf("\n");
	}
} 

void anction_goto_form(){
	
	
	//(1)填写acc-->999
	acc_form(); 
	//(2) 填写goto()表，输入大写 
	goto_form();
	
	
	//(3)填写r负数
	action_r_form();
	 
	 
	 //printf("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww\n");
	 
	//(4)填写s正数 
	action_s_form();
	//printf("-----------------%d\n",lt->I_01); 
	 
	 
	 
	 
	output_action_goto();//输出acion_goto表 
}

void output_lr_analyse(){
	LR *lt=Ips->next;
	
	while(lt!=NULL){
		printf("当前是I(%d),有%d条语句,输入字符是%c\n",lt->I_01,lt->num,lt->c);
		printf("语句为：\n");
		f(lt->css->next); 
		lt=lt->next;
	}
} 

void get_string(char *st){
    size_t len = strlen(st);
    char* new_st = malloc(len + 3);
    if (new_st != NULL) {
        strcpy(new_st, st);
        new_st[len] = '#';
        new_st[len + 1] = 0;
        // 使用 new_st 替换原 st，并确保释放旧内存（如果动态分配）
        // free(st);  // 仅当 st 是动态分配时才可调用
        str = strdup(new_st);
    }
}

int jc_lr_form(int h,char c){
	
	int i;
	
	int flag=0;//记录是action表的内容还是goto表的内容 
	
	int x;
	
	//遍历action 
	for(i=0;i<at_num;i++){
		if(at[i]==c){
			x=i;
			flag=1;//action表
			break; 
		}
	}
	
	for(i=0;i<gt_num;i++){
		if(gt[i]==c){
			x=at_num+i;
			flag=2;
			break;
		}
	}
	
	if(flag==1){//在action中 
		if(act_gt[h][x]>0&&act_gt[h][x]!=32){
			//S
			return act_gt[h][x];
		} 
		
		if(act_gt[h][x]<0){
			return act_gt[h][x];
			//r
		}
		
		if(act_gt[h][x]==999){
			//接受 
			return 9999;
		}
		
		if(act_gt[h][x]==32){
			//出错 
			return 2222;
		}
		
	}
	
	if(flag==2){//说明在goto表中 
		
		if(act_gt[h][x]!=32){//状态转移 
		    return act_gt[h][x]+1000;
		}else{
			//出错 
			return 2222;
		} 
		
	} 
	
	if(flag==0){
		//出错 
		return 2222;
	}
	
} 

void out_fhz(){
	
	printf("%d    符号栈：",idx++);
	
	int i;
	for(i=0;i<=fhz_num;i++){
		if(fhz[i]<=0){
			printf("%d",fhz[i]*-1);
		}else{
			printf("%c",fhz[i]);
		}
		
	}
	printf("          ");
}

void out_str(){
	printf("当前输入：");
	
	int i;
	for(i=str_num;i<strlen(str);i++){
		printf("%c",str[i]);
	}
	printf("          ");
}

//找标号为num的表达式 
CSS* guiyue(int num){
	CSS *p=Ips->next->css->next;
	while(p!=NULL){
		if(p->num==num){
			return p;
		}
		
		p=p->next;
	} 
}

void lr_process(){
	//初始符号栈#0
	fhz[fhz_num]='#';
	fhz_num++;
	fhz[fhz_num]=0*(-1);//状态（用负数来表示状态，将状态与符号区分开来） 
	while(1){
		//查看符号栈栈顶元素，和串的栈顶元素
		//查分析表
		 int sr_num=jc_lr_form(fhz[fhz_num]*-1,str[str_num]);//(状态，输入) 
		 
		 //sr_num==2222//出差错
		 if(sr_num==2222){
		 	printf("出错，不可识别\n");
		 	break; 
		 }
		 if(sr_num>0&&sr_num<1000){
		 	out_fhz();//输出栈内容 
			out_str(); //当前输入
			if(sr_num==999){
				printf("接收accept\n"); 
				break; 
			}else{
				printf("移进：S%d\n",sr_num); 
			}
		 	//先移入符号，再移入状态
		 	//移入符号 
		 	fhz_num++;//符号栈指针+1 
		 	fhz[fhz_num]=str[str_num];
		 	str_num++;//输入串指针后移 
		 	//移入状态 
		 	fhz_num++;
		 	fhz[fhz_num]=sr_num*-1; 
		 }
		 if(sr_num<0){//归约 
		 	out_fhz();//输出栈内容 
			out_str(); //当前输入
			//在I0中找标号为sr_num*-1的	//sr_num*-1,要归约的表达式
			CSS *csst01=guiyue(sr_num*-1);
			printf("归约：R%d(%c->%s)\n",sr_num*-1,csst01->left,csst01->right); 
			//fhz指针后移一位，换成csst01->left
			fhz_num=fhz_num-2*strlen(csst01->right)+1;
			fhz[fhz_num]=csst01->left;
			 
			int zt=jc_lr_form(fhz[fhz_num-1]*-1,fhz[fhz_num]);
			if(zt>1000&&zt<2000){
			    fhz_num++;
			 	fhz[fhz_num]=(zt-1000)*-1;
			}else{
			 	if(zt==9999){
			 		printf("acc，接收\n");
		 			break;
			 	}else{
			 		printf("出错，不可识别\n");
		 			break;
			 	}
			} 
		}
		if(sr_num==9999){
		 	printf("acc，接收\n");
		 	break;
		}
	} 
}

void to_parsing_lr0(void *self,char *st){
    Parsing_LR0 *p=(Parsing_LR0*)self;
    fhz_num=0;
    str_num=0;
    idx=0;
    //输入分析串
    printf("\n\033[33m=============================分隔符========================================\033[0m\n");
	get_string(st); 
	lr_process(); 
	return;
}

Parsing_LR0 *parsing_lr0(char*rulefile){
    Parsing_LR0 *p = malloc(sizeof(Parsing_LR0));  
    get_g(rulefile);//文法的输入 
	action();//找action序列（非大写） 
	gotoo();//找大写非终结符
	
	init_gt_01();//初始化gt_01表 
	
	lr_save(); //存储输入的文法在变量lr中
	
	into_I0();//初始化I0;并初始头结点 
	printf("\033[32m===================开始分析=====================\033[0m\n");
	printf("=====================I(0)为=====================\n");
	f(Ips->next->css->next);
	printf("================================================\n");
	
	lr_analyse(); //项目集规范族 Ips是头指针 
	
	//清屏函数 
	//system("cls");
	
	output_lr_analyse();//输出项目集 
	
	printf("======================ACTION GOTO表==========================\n");
	anction_goto_form();//构造LR分析表，并输出
    p->to_parsing=to_parsing_lr0;
    return p;
}